package rmmk.algorithms.features;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;

import rmmk.algorithms.features.abstraction.AbstractFeatureExtractor;
import rmmk.framework.datasources.Document;

/**
 * Klasa odpowiedzialna za przechowywanie, wyliczanie oraz cachowanie cech 
 * @author Marcin
 *
 */
public class FeatureManager {
	
	private HashMap<Document, Double[]> cache = new HashMap<>();
	private Vector<AbstractFeatureExtractor> features = new Vector<>();

	/**
	 * Dodaje cechy do obliczeń
	 * @param features
	 */
	public void addFeature(AbstractFeatureExtractor... features) {
		for (AbstractFeatureExtractor f : features)
			this.addFeature(f);
	}
	
	public void addFeature(ArrayList<AbstractFeatureExtractor> features) {
		for (AbstractFeatureExtractor f : features)
			this.addFeature(f);
	}

	/**
	 * Dodaje pojedyńczą ceche do obliczeń
	 * @param feature
	 */
	public void addFeature(AbstractFeatureExtractor feature) {
		this.cache.clear();
		
		this.features.add(feature);
	}

	/**
	 * Wylicza wektor cech dla pojedyńczego dokumentu
	 * @param document 
	 * @return
	 */
	public Double[] calculateFeatureFor(Document document)
	{
		if(this.cache.containsKey(document)) return this.cache.get(document);
		
		int vectorLenght = 0;
		for(AbstractFeatureExtractor afe : this.features)
			vectorLenght+= afe.getFeatureSize();
		
		Double[] resp = new Double[vectorLenght];
		
		int i = 0;
		for(AbstractFeatureExtractor afe : this.features){
			Double[] val = afe.calculate(document);
			
			for(Double d : val)
				resp[i++] = d;
		}
		
		this.cache.put(document, resp);
		
		return resp;
	}
	
	/**
	 * Wylicza listę wektorów cech dla podanych dokumentów
	 * @param documents
	 * @return
	 */
	public ArrayList<Double[]> calculateFeatureFor(Document... documents){
		ArrayList<Double[]> resp = new ArrayList<>();
		
		for(Document d : documents)
			resp.add(this.calculateFeatureFor(d));
		
		return resp;
	}

	/**
	 * Zwraca aktualną długość wektora cech
	 * @return
	 */
	public int getVectorLenght()
	{
		int sum = 0;
		
		for(AbstractFeatureExtractor abe : this.features)
			sum += abe.getFeatureSize();
		
		return sum;
	}

	public Vector<AbstractFeatureExtractor> getFeatures() {
		return features;
	}
	
	
}
